package core

import (
	"errors"
	"qiuya/util"
)

func lookup(db string, source *[]map[string]interface{}, _lookup map[string]interface{}, hasCopy *bool) (err error) {
	//必须保证有这四个值
	var from, localField, foreignField, as string
	from, ok0 := _lookup["from"].(string)
	localField, ok1 := _lookup["localField"].(string)
	foreignField, ok2 := _lookup["foreignField"].(string)
	as, ok3 := _lookup["as"].(string)
	if !ok0 || !ok1 || !ok2 || !ok3 {
		err = errors.New("错误的$lookup格式")
		return
	}
	var col = GetCollection(db, from)
	col.RWLock.RLock()
	defer col.RWLock.RUnlock()

	//做出连接的map
	var cache = map[interface{}][]interface{}{}
	for _, v := range col.Mp.Values {
		var fid = v[foreignField]
		if fid == nil {
			continue
		}
		cache[fid] = append(cache[fid], v)
	}

	//检查集合，是否有相关联的字段
	var dest = []map[string]interface{}{}
	for _, v := range *source {
		var lid = v[localField]
		var links = cache[lid]
		var cp = v //map[string]interface{}
		if !*hasCopy {
			cp = util.CopyMap(v)
		}
		cp[as] = util.CopyArray(links)
		if cp[as] == nil {
			cp[as] = []interface{}{}
		}
		dest = append(dest, cp)
	}
	*hasCopy = true
	*source = dest

	return
}

func graphLookup(db string, source *[]map[string]interface{}, _lookup map[string]interface{}, hasCopy *bool) (err error) {
	var from, connectFromField, connectToField, as string
	from, ok0 := _lookup["from"].(string)
	connectFromField, ok1 := _lookup["connectFromField"].(string)
	connectToField, ok2 := _lookup["connectToField"].(string)
	as, ok3 := _lookup["as"].(string)
	if !ok0 || !ok1 || !ok2 || !ok3 {
		err = errors.New("错误的$graphLookup格式")
		return
	}
	var col = GetCollection(db, from)
	col.RWLock.RLock()
	defer col.RWLock.RUnlock()

	//做出连接的map
	var cache = map[interface{}][]map[string]interface{}{}
	for _, v := range col.Mp.Values {
		var fid = v[connectToField]
		if fid == nil {
			continue
		}
		cache[fid] = append(cache[fid], v)
	}

	//检查集合，是否有相关联的字段
	var MAX_LIMIT = 100
	var dest = []map[string]interface{}{}
	for _, v := range *source {
		var cp = v //map[string]interface{}
		if !*hasCopy {
			cp = util.CopyMap(v)
		}
		//准备池
		var pool = []map[string]interface{}{v}
		var i = 0
		for ; i < len(pool) && i < MAX_LIMIT; i++ {
			var vv = pool[i]
			var lid = vv[connectFromField]
			var links = cache[lid]
			for _, link := range links {
				pool = append(pool, util.CopyMap(link))
			}
		}
		if i > MAX_LIMIT {
			err = errors.New("$graphLookup需要查找的对象是否有循环引用？")
			return
		}
		cp[as] = pool[1:]
		dest = append(dest, cp)
	}

	*hasCopy = true
	*source = dest
	return
}
